package service

import (
	"errors"
	"github.com/go-admin-team/go-admin-core/sdk/service"
	"gorm.io/gorm"
	"strconv"
	"strings"
	"time"
	"tuowei.com/app/api/models"
	"tuowei.com/app/api/service/dto"
	"tuowei.com/common/actions"
	cDto "tuowei.com/common/dto"
	"tuowei.com/pkg/xlog"
)

type ApiTestExercises struct {
	service.Service
}

func (e *ApiTestExercises) GetPageQuestionBank(c *dto.ApiExercisesGetPageReq, p *actions.DataPermission, list *[]models.SysExercises, count *int64) error {
	var err error
	var data models.SysExercises
	var model models.SysExercises
	//c.PublishRange = strings.Replace(c.PublishRange, "市", "", -1)
	c.PublishRange = strings.TrimRight(c.PublishRange, "市")
	c.PublishRange = strings.TrimRight(c.PublishRange, "盟")
	err = e.Orm.Debug().Model(&model).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
			actions.Permission(data.TableName(), p),
		).
		//Where("status = ?", 1).
		Order("id DESC").Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return err
	}
	return nil
}

// GetSysDeptList 获取组织数据
func (e *ApiTestExercises) getList(linkId interface{}, list *[]models.SysQuestionBankWare) error {
	var err error
	var data models.SysQuestionBankWare
	err = e.Orm.Model(&data).Where("question_bank_id = ?", linkId).Where("is_show = ?", 0).Find(list).Error
	if err != nil {
		e.Log.Errorf("db error:%s", err)
		return err
	}
	return nil
}

// GetSysDeptList 获取组织数据
func (e *ApiTestExercises) getExerciseQuestionCount(linkId interface{}) (map[int]int, error) {
	var err error
	var data models.SysQuestionBankWare
	list := make([]models.SysQuestionBankWare, 0)
	err = e.Orm.Model(&data).Where("question_bank_id = ?", linkId).Where("is_show = ?", 0).Find(&list).Error
	if err != nil {
		e.Log.Errorf("db error:%s", err)
		return nil, err
	}
	arr := make([]int, len(list))
	for _, v := range list {
		arr = append(arr, v.Id)
	}
	var questionLinkList []models.SysQuestionBankLink
	err = e.Orm.Where("link_type = ?", 2).Where("link_id = ?", linkId).Where("chapter_id in (?)", arr).Find(&questionLinkList).Error
	if err != nil {
		e.Log.Errorf("db error:%s", err)
		return nil, err
	}
	questionBankCountList := make(map[int]int, len(questionLinkList))
	for _, vs := range questionLinkList {
		tmp := strings.Split(vs.QuestionBankStr, ",")
		questionBankCountList[vs.ChapterId] = len(tmp)
	}
	return questionBankCountList, nil
}

// Call 递归构建章节树
func (e *ApiTestExercises) QuestionBankWareTreeCall(linkID interface{}) (m []models.QuestionBankWareTree, err error) {
	var list []models.SysQuestionBankWare
	err = e.getList(linkID, &list)
	if err != nil {
		return nil, err
	}
	m = make([]models.QuestionBankWareTree, 0)
	for i := 0; i < len(list); i++ {
		if list[i].Pid != 0 {
			continue
		}
		s := models.QuestionBankWareTree{}
		s.Id = list[i].Id
		s.Name = list[i].Name
		s.Count = list[i].Count
		//s.QuestionBankId = list[i].QuestionBankId
		//s.IsContainExercise = -1
		//s.IsFree = list[i].IsFree
		deptsInfo, err := e.questionBankWareTreeCall(linkID, &list, s)
		if err != nil {
			return nil, err
		}
		m = append(m, *deptsInfo)
	}
	return
}

func (e *ApiTestExercises) GetQuestionBankListCount(linkId, chapterId int) (int, bool) {
	if str, ok := e.Orm.Debug().Where("link_id = ?", linkId).Where("chapter_id = ?", chapterId).Where("link_type = ?", 2).Get("question_bank_str"); !ok {
		return 0, false
	} else {
		arr := strings.Split(str.(string), ",")
		return len(arr), true
	}
}

// Call 递归构造组织数据
func (e *ApiTestExercises) questionBankWareTreeCall(linkID interface{}, deptList *[]models.SysQuestionBankWare, result models.QuestionBankWareTree) (*models.QuestionBankWareTree, error) {
	list := *deptList
	maps, err := e.getExerciseQuestionCount(linkID)
	if err != nil {
		return nil, err
	}
	min := make([]models.QuestionBankWareTree, 0)
	for j := 0; j < len(list); j++ {
		if result.Id != list[j].Pid {
			continue
		}
		count := maps[list[j].Id]
		if count == 0 {
			continue
		}
		mi := models.QuestionBankWareTree{Id: list[j].Id, Name: list[j].Name, Children: []models.QuestionBankWareTree{}}
		ms, _ := e.questionBankWareTreeCall(linkID, deptList, mi)
		min = append(min, *ms)
	}
	result.Children = min
	return &result, nil
}

func (e *ApiTestExercises) GetPracticeList(c *dto.GetPracticeListByChapterIdReq, studentId int) (list []*models.QuestionBankList, err error) {
	var data models.SysQuestionBankLink
	var questionBank models.SysQuestionBank
	db := e.Orm.Debug().Model(data).
		Where("link_type = ?", c.ExerciseType)
	if c.LinkId != 0 {
		db = db.Where("link_id = ?", c.LinkId)
	}
	if c.ChapterId != 0 {
		db = db.Where("chapter_id = ?", c.ChapterId)
	}
	err = db.First(&data).Error
	if err != nil {
		return nil, err
	}
	arr := strings.Split(data.QuestionBankStr, ",")
	arrInt := make([]int, 0)
	for _, vs := range arr {
		vs, _ := strconv.Atoi(vs)
		arrInt = append(arrInt, vs)
	}
	db2 := e.Orm.Debug().Model(&questionBank).Where("id in ?", arrInt)
	if c.SubjectType != "" {
		db2 = db2.Where("subject_type = ?", c.SubjectType)
	}
	err = db2.Find(&list).Error
	if err != nil {
		return nil, err
	}
	exIds := make([]int, 0)
	for _, v := range list {
		exIds = append(exIds, v.Id)
	}
	//// 获取练习题的做题数
	exerciseRecords := make([]models.SysExerciseRecord, 0) //new(models.SysExerciseRecord)
	e.Orm.Where("ex_type = ?", c.ExerciseType).Where("student_id = ?", studentId).Where("ex_id in (?)", exIds).Select("ex_id", "nums").Find(&exerciseRecords)
	id2num := make(map[int]int)
	for _, v := range exerciseRecords {
		id2num[v.ExId] = v.Nums
	}
	for _, v := range list {
		v.Nums = id2num[v.Id]
	}
	return list, nil
}

func (e *ApiTestExercises) GetAchievementReport(req *dto.GetAchievementReportReq, data *models.SysPracticeRecord) error {
	var model models.SysPracticeRecord
	err := e.Orm.Model(&model).Debug().
		Where("student_id = ?", req.StudentId).
		Where("ex_type = ?", req.ExerciseType).
		Where("obj_id = ?", req.GetId()).
		Order("id desc").
		First(data).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New("查看对象不存在或无权查看")
		return err
	}

	return nil
}

func (e *ApiTestExercises) StartAnswer(req *dto.SubmitReq, studentID int) (int, error) {
	var err error
	if req.ExerciseType == 1 {
		var model models.SysCourse
		err = e.Orm.Debug().Model(model).Where("course_id = ?", req.ObjId).First(&model).Error
	} else if req.ExerciseType == 2 {
		var model models.SysExercises
		err = e.Orm.Debug().Model(model).Where("id = ?", req.ObjId).First(&model).Error
	} else if req.ExerciseType == 3 {
		var model models.SysExamination
		err = e.Orm.Debug().Model(model).Where("id = ?", req.ObjId).First(&model).Error
	}
	if err != nil {
		return 1, err
	}

	//if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
	//	return 1, errors.New("数据不存在或已被删除")
	//} else {
	var data models.SysPracticeRecordInsert
	//err = e.Orm.Debug().Model(data).
	//	Where("student_id = ?", studentID).
	//	Where("ex_type = ?", req.ExerciseType).
	//	Where("obj_id = ?", req.ObjId).First(&data).Error
	//if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
	req.Generate(&data)
	data.StudentId = studentID
	data.ObjId = req.ObjId
	data.ExType = req.ExerciseType
	data.ChapterId = req.ChapterId
	data.StartAnswerTime = time.Now().Unix()
	data.Status = 1
	err = e.Orm.Debug().Transaction(func(tx *gorm.DB) error {
		err = tx.Create(&data).Error
		if err != nil {
			return err
		}
		if req.ExerciseType == 1 {
			var learningList models.LearningList
			err = tx.Model(learningList).
				Where("course_id = ?", req.ObjId).
				Where("buyer_id = ?", studentID).
				Update("status", 1).Error
			if err != nil {
				return err
			}
		}
		return nil
	})

	if err != nil {
		return 1, err
	}

	//} else {
	//	switch req.ExerciseType {
	//	case 1:
	//		return 2, errors.New("练习正在进行，是否继续")
	//	case 2:
	//		return 3, errors.New("练习正在进行，是否继续")
	//	case 3:
	//		return 2, errors.New("考试正在进行，是否继续")
	//	}
	//}
	//}
	return 0, nil
}

func (e *ApiTestExercises) UpdatePracticeRecord(req *dto.SubmitReq, studentID int) error {
	var model models.SysPracticeRecordInsert
	err := e.Orm.Debug().Model(model).Where("student_id = ?", studentID).
		Where("ex_type = ?", req.ExerciseType).
		Where("obj_id = ?", req.ObjId).Order("id desc").First(&model).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		return err
	} else {
		var exerciseRecordModel models.SysExerciseRecord
		var errorCount = int64(0)
		var correctCount = int64(0)
		var correctRate = int64(0)
		err = e.Orm.Debug().Model(exerciseRecordModel).
			Where("ex_type = ?", req.ExerciseType).
			Where("link_id = ?", req.ObjId).
			Where("practice_id  = ?", model.Id).
			Where("status = ?", 0).Count(&errorCount).Error
		err = e.Orm.Debug().Model(exerciseRecordModel).
			Where("ex_type = ?", req.ExerciseType).
			Where("link_id = ?", req.ObjId).
			Where("practice_id  = ?", model.Id).
			Where("status = ?", 1).Count(&correctCount).Error
		if (errorCount + correctCount) == 0 {
			correctRate = 0
		} else {
			correctRate = correctCount / (correctCount + errorCount) * 100
		}
		//list := make([]*models.ExerciseRecordList,0)
		//err = e.Orm.Debug().Model(exerciseRecordModel).
		//	Where("ex_type = ?",req.ExerciseType).
		//    Where("link_id = ?",req.ObjId).
		//	Where("practice_id  = ?", model.Id).Find(&list).Error
		//if err != nil {
		//	return err
		//}

		updates := map[string]interface{}{
			"number_of_exercises":         gorm.Expr("number_of_exercises + ?", 1),
			"correct_count":               correctCount,
			"error_count":                 errorCount,
			"end_answer_time":             time.Now().Unix(),
			"last_leave_question_bank_id": req.LastLeaveQuestionBankId,
			"status":                      2,
			"correct_rate":                correctRate,
		}
		err = e.Orm.Model(model).Updates(updates).Error
		if err != nil {
			return err
		}

		return nil
	}
}

func (e *ApiTestExercises) RecordPracticeLeave(req *dto.RecordLeavePracticeReq, studentID int) error {
	var data models.PracticeRecord
	var err error
	err = e.Orm.Debug().Where("student_id = ?", studentID).
		Where("ex_type = ?", req.ExType).
		Where("obj_id = ?", req.QuestionBankId).First(&data).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		xlog.Debug(err)
		return nil
	}
	if err = e.Orm.Debug().Model(data).
		Where("student_id = ?", studentID).
		Where("ex_type = ?", req.ExType).
		Where("obj_id = ?", req.ObjId).
		Update("last_leave_question_bank_id", req.QuestionBankId).Error; err != nil {
		return err
	}
	return nil
}

func handler() {

}
